package com.wemirr.platform.authority.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import com.wemirr.framework.boot.service.impl.SuperServiceImpl;
import com.wemirr.framework.boot.utils.BeanPlusUtil;
import com.wemirr.framework.database.mybatis.auth.DataScope;
import com.wemirr.framework.database.mybatis.conditions.Wraps;
import com.wemirr.platform.authority.domain.dto.RoleDTO;
import com.wemirr.platform.authority.domain.entity.Role;
import com.wemirr.platform.authority.domain.entity.RoleOrg;
import com.wemirr.platform.authority.domain.entity.RoleRes;
import com.wemirr.platform.authority.domain.entity.UserRole;
import com.wemirr.platform.authority.mapper.RoleMapper;
import com.wemirr.platform.authority.service.RoleOrgService;
import com.wemirr.platform.authority.service.RoleResService;
import com.wemirr.platform.authority.service.RoleService;
import com.wemirr.platform.authority.service.UserRoleService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;


/**
 * <p>
 * 业务实现类
 * 角色
 * </p>
 *
 * @author Levin
 * @since 2019-07-03
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RoleServiceImpl extends SuperServiceImpl<RoleMapper, Role> implements RoleService {

    private final RoleOrgService roleOrgService;
    private final RoleResService roleResService;
    private final UserRoleService userRoleService;


    @Override
    public List<Role> list(DataScope scope) {
        return baseMapper.list(scope);
    }

    /**
     * 删除角色时，需要级联删除跟角色相关的一切资源：
     * 1，角色本身
     * 2，角色-组织：
     * 3，角色-权限（菜单和按钮）：
     * 4，角色-用户：角色拥有的用户
     * 5，用户-权限：
     */
    @Override
    public boolean removeByIdWithCache(List<Long> ids) {
        if (ids.isEmpty()) {
            return true;
        }
        boolean removeFlag = baseMapper.deleteBatchIds(ids) > 0;
        roleOrgService.remove(Wraps.<RoleOrg>lbQ().in(RoleOrg::getRoleId, ids));
        roleResService.remove(Wraps.<RoleRes>lbQ().in(RoleRes::getRoleId, ids));
        userRoleService.listObjs(
                Wraps.<UserRole>lbQ().select(UserRole::getUserId).in(UserRole::getRoleId, ids),
                Convert::toLong);
        userRoleService.remove(Wraps.<UserRole>lbQ().in(UserRole::getRoleId, ids));
        return removeFlag;
    }

    /**
     * 1，保存角色
     * 2，保存 与组织的关系
     *
     * @param data
     * @param userId 用户id
     */
    @Override
    public void saveRole(Long userId, RoleDTO data) {
        Role role = BeanPlusUtil.toBean(data, Role.class);
        role.setReadonly(false);
        super.save(role);
        saveRoleOrg(role, data.getOrgList());
    }

    @Override
    public void updateRole(Long roleId, Long userId, RoleDTO data) {
        Role role = BeanPlusUtil.toBean(data, Role.class);
        role.setId(roleId);
        baseMapper.updateById(role);

        roleOrgService.remove(Wraps.<RoleOrg>lbQ().eq(RoleOrg::getRoleId, roleId));
        saveRoleOrg(role, data.getOrgList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveUserRole(Long roleId, List<Long> userIdList) {
        this.userRoleService.remove(Wraps.<UserRole>lbQ().eq(UserRole::getRoleId, roleId));
        final List<UserRole> userRoles = userIdList.stream().map(userId -> UserRole.builder()
                .roleId(roleId).userId(userId).build())
                .collect(Collectors.toList());
        this.userRoleService.saveBatch(userRoles);
    }

    private void saveRoleOrg(Role role, List<Long> orgList) {
        // 根据 数据范围类型 和 勾选的组织ID， 重新计算全量的组织ID
        if (CollectionUtil.isNotEmpty(orgList)) {
            List<RoleOrg> list = orgList.stream().map((orgId) -> RoleOrg.builder().orgId(orgId).roleId(role.getId()).build()
            ).collect(Collectors.toList());
            roleOrgService.saveBatch(list);
        }
    }
}
